{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Variational Quantum Classifier (VQC)\n",
    "\n",
    "The QSVM notebook demonstrated a kernel based approach. This notebook shows a variational method using the [VQC](https://qiskit.org/documentation/stubs/qiskit.aqua.algorithms.VQC.html) algorithm.\n",
    "\n",
    "For further information see also the following reference, as given in the QSVM notebook, that also describes this approach:\n",
    "\"Supervised learning with quantum enhanced feature spaces,\" [arXiv: 1804.11326](https://arxiv.org/pdf/1804.11326.pdf)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "\n",
    "from qiskit import BasicAer\n",
    "from qiskit.aqua import QuantumInstance, aqua_globals\n",
    "from qiskit.aqua.algorithms import VQC\n",
    "from qiskit.aqua.components.optimizers import SPSA\n",
    "from qiskit.circuit.library import TwoLocal, ZZFeatureMap\n",
    "from qiskit.aqua.utils import split_dataset_to_data_and_labels, map_label_to_class_name\n",
    "\n",
    "seed = 10599\n",
    "aqua_globals.random_seed = seed"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As per the QSVM notebook again we will use the ad hoc dataset as described in the above referenced paper. From the dataset we take samples for use as training, testing and the final prediction (datapoints)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f50bf165e80>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'A': 0, 'B': 1}\n"
     ]
    }
   ],
   "source": [
    "from qiskit.ml.datasets import ad_hoc_data, sample_ad_hoc_data\n",
    "\n",
    "feature_dim = 2\n",
    "sample_total, training_input, test_input, class_labels = ad_hoc_data(\n",
    "    training_size=20, \n",
    "    test_size=10, \n",
    "    n=feature_dim, \n",
    "    gap=0.3, \n",
    "    plot_data=True\n",
    ")\n",
    "extra_test_data = sample_ad_hoc_data(sample_total, 10, n=feature_dim)\n",
    "datapoints, class_to_label = split_dataset_to_data_and_labels(extra_test_data)\n",
    "print(class_to_label)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "With the dataset ready we can setup the [VQC](https://qiskit.org/documentation/stubs/qiskit.aqua.algorithms.VQC.html) algorithm to do a classification. We use the [ZZFeatureMap](https://qiskit.org/documentation/stubs/qiskit.circuit.library.ZZFeatureMap.html) data encoding circuit from the Qiskit circuit library, like we did with QSVM. But this is a variational algorithm so we need a variational form, i.e. parameterized circuit, whose parameters can be varied by an optimizer when computing VQC's cost function. For this we choose [TwoLocal](https://qiskit.org/documentation/stubs/qiskit.circuit.library.TwoLocal.html) from the Qiskit circuit library. As the qasm_simulator has shot noise we choose to use [SPSA](https://qiskit.org/documentation/stubs/qiskit.aqua.components.optimizers.SPSA.html) which is designed to perform under noisy conditions.\n",
    "\n",
    "Here the BasicAer `qasm_simulator` is used with 1024 shots."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Testing success ratio: 0.9\n",
      "\n",
      "Prediction from datapoints set:\n",
      "  ground truth: ['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B']\n",
      "  prediction:   ['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B']\n",
      "  success rate: 100.0%\n"
     ]
    }
   ],
   "source": [
    "feature_map = ZZFeatureMap(feature_dimension=feature_dim, reps=2)\n",
    "optimizer = SPSA(maxiter=40, c0=4.0, skip_calibration=True)\n",
    "var_form = TwoLocal(feature_dim, ['ry', 'rz'], 'cz', reps=3)\n",
    "vqc = VQC(optimizer, feature_map, var_form, training_input, test_input, datapoints[0])\n",
    "\n",
    "backend = BasicAer.get_backend('qasm_simulator')\n",
    "quantum_instance = QuantumInstance(backend, shots=1024, seed_simulator=seed, seed_transpiler=seed)\n",
    "\n",
    "result = vqc.run(quantum_instance)\n",
    "\n",
    "print(f'Testing success ratio: {result[\"testing_accuracy\"]}')\n",
    "print()\n",
    "print('Prediction from datapoints set:')\n",
    "print(f'  ground truth: {map_label_to_class_name(datapoints[1], vqc.label_to_class)}')\n",
    "print(f'  prediction:   {result[\"predicted_classes\"]}')\n",
    "predicted_labels = result[\"predicted_labels\"]\n",
    "print(f'  success rate: {100*np.count_nonzero(predicted_labels == datapoints[1])/len(predicted_labels)}%')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now VQC, as well as QSVM, have `train`, `test` and `predict` methods. The `run` method, as used above, will call these in turn based on whatever data was supplied to the algorithm. But the methods called directly to say train a model and then do predict. Since the vqc instance has already been trained, lets predict another set of sample datapoints by directly calling `predict`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Prediction from more_datapoints set:\n",
      "  ground truth: ['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B']\n",
      "  prediction:   ['A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B', 'B']\n",
      "  success rate: 100.0%\n"
     ]
    }
   ],
   "source": [
    "more_test_data = sample_ad_hoc_data(sample_total, 10, n=feature_dim)\n",
    "more_datapoints, _ = split_dataset_to_data_and_labels(more_test_data)\n",
    "\n",
    "predicted_probabilities, predicted_labels = vqc.predict(datapoints[0])\n",
    "\n",
    "print('Prediction from more_datapoints set:')\n",
    "print(f'  ground truth: {map_label_to_class_name(more_datapoints[1], vqc.label_to_class)}')\n",
    "print(f'  prediction:   {map_label_to_class_name(predicted_labels, vqc.label_to_class)}')\n",
    "print(f'  success rate: {100*np.count_nonzero(predicted_labels == more_datapoints[1])/len(predicted_labels)}%')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Finally I will note that the Qiskit classifier algorithms can `save_model` after training and also `load_model` that had been previously saved."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2019-08-22T01:49:36.816822Z",
     "start_time": "2019-08-22T01:49:36.806994Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<h3>Version Information</h3><table><tr><th>Qiskit Software</th><th>Version</th></tr><tr><td>Qiskit</td><td>0.23.1</td></tr><tr><td>Terra</td><td>0.16.1</td></tr><tr><td>Aer</td><td>0.7.1</td></tr><tr><td>Ignis</td><td>0.5.1</td></tr><tr><td>Aqua</td><td>0.8.1</td></tr><tr><td>IBM Q Provider</td><td>0.11.1</td></tr><tr><th>System information</th></tr><tr><td>Python</td><td>3.6.1 |Continuum Analytics, Inc.| (default, May 11 2017, 13:09:58) \n",
       "[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)]</td></tr><tr><td>OS</td><td>Linux</td></tr><tr><td>CPUs</td><td>1</td></tr><tr><td>Memory (Gb)</td><td>5.827335357666016</td></tr><tr><td colspan='2'>Fri Nov 13 15:27:38 2020 EST</td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div style='width: 100%; background-color:#d5d9e0;padding-left: 10px; padding-bottom: 10px; padding-right: 10px; padding-top: 5px'><h3>This code is a part of Qiskit</h3><p>&copy; Copyright IBM 2017, 2020.</p><p>This code is licensed under the Apache License, Version 2.0. You may<br>obtain a copy of this license in the LICENSE.txt file in the root directory<br> of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.<p>Any modifications or derivative works of this code must retain this<br>copyright notice, and modified files need to carry a notice indicating<br>that they have been altered from the originals.</p></div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import qiskit.tools.jupyter\n",
    "%qiskit_version_table\n",
    "%qiskit_copyright"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.1"
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
